package se.sics.gvod.nat.hp.client;

import se.sics.gvod.config.HpClientConfiguration;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import se.sics.gvod.timer.TimeoutId;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.Semaphore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import se.sics.gvod.net.VodAddress;
import se.sics.gvod.nat.common.PortInit;
import se.sics.gvod.nat.common.PortReservoirComp;
import se.sics.gvod.nat.emu.IpIntPair;
import se.sics.gvod.net.Nat;
import se.sics.gvod.stun.client.StunClient;
import se.sics.gvod.stun.client.StunPort;
import se.sics.gvod.stun.client.events.GetNatTypeRequest;
import se.sics.gvod.stun.client.events.GetNatTypeResponse;
import se.sics.gvod.stun.client.events.GetNatTypeResponseRuleExpirationTime;
import se.sics.gvod.stun.client.events.StunClientInit;
import se.sics.gvod.stun.client.simulator.NetworkSimulator;
import se.sics.gvod.stun.client.simulator.NetworkSimulatorInit;
import se.sics.gvod.stun.server.StunServer;
import se.sics.gvod.stun.server.events.StunServerInit;
import se.sics.kompics.ChannelFilter;
import se.sics.kompics.Component;
import se.sics.kompics.ComponentDefinition;
import se.sics.kompics.Handler;
import se.sics.gvod.address.Address;
import se.sics.gvod.common.Self;
import se.sics.gvod.common.SelfNoParents;
import se.sics.gvod.common.SelfNoUtility;
import se.sics.gvod.common.util.ToVodAddr;
import se.sics.gvod.net.VodNetwork;
import se.sics.gvod.net.NatNetworkControl;
import se.sics.gvod.net.msgs.DirectMsg;
import se.sics.gvod.nat.hp.client.events.OpenConnectionRequest;
import se.sics.gvod.nat.hp.client.events.OpenConnectionResponse;
import se.sics.gvod.hp.events.OpenConnectionResponseType;
import se.sics.gvod.hp.msgs.HpRegisterMsg;
import se.sics.gvod.nat.hp.rs.RendezvousServer;
import se.sics.gvod.nat.hp.rs.RendezvousServer.RegisteredClientRecord;
import se.sics.gvod.config.RendezvousServerConfiguration;
import se.sics.gvod.config.StunClientConfiguration;
import se.sics.gvod.nat.hp.rs.RendezvousServerInit;
import se.sics.gvod.net.msgs.RewriteableMsg;
import se.sics.gvod.config.StunServerConfiguration;
import se.sics.gvod.hp.msgs.TConnectionMsg;
import se.sics.gvod.nat.emu.DistributedNatGatewayEmulator;
import se.sics.gvod.nat.emu.events.DistributedNatGatewayEmulatorInit;
import se.sics.gvod.stun.upnp.UpnpPort;
import se.sics.gvod.timer.ScheduleTimeout;
import se.sics.gvod.timer.Timeout;
import se.sics.gvod.timer.Timer;
import se.sics.gvod.timer.UUID;
import se.sics.gvod.timer.java.JavaTimer;

//  {m(EI)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PP)_alt(PC)_f(EI)} - FAILED
// 
//
//  +---------------------------------------+     +-----------------------------------------+      +-------------------------------------+
//  | ..............    .................   |     |  ..............     ................    |      | ..............      .............   |
//  | : Stun       :    : Hole Punching :   |     |  : Stun       :     :Hole Punching :    |      | :Stun Server :      :zServer/   :   |
//  | : Client A   :    : Client A      :   |     |  : Client B   :     :Clint B       :    |      | :S1 and S2   :      :Rendezvous :   |
//  | :............:    :...............:   |     |  :............:     :..............:    |      | :......../...:      :Server     :   |
//  |            `.                   |     |     |           \                  /          |      |         |           :....../....:   |
//  |              \                  |     |     +------------+----------------+-----------+      +--------++----------------.'---------+
//  +---------------`.----------------+-----+                  \               /                           //                /
//                    `.              |                         \             /                           |                .'
//                      `.            |                          \          .'                            /               /
//                        \           |                           |        /                             /              .'
//                         `.         |                           \       /                             /              /
//                           `.-------+-------+              +-----+-----+-----+                       /             .'
//                           |                |              |                 |                      |             /
//                           |     Nat A      |              |     Nat B       |                      /           .'
//                           |                |              |                 |                     /           /
//                           +-------------.=-+              +----------`-.----+                    /          .'
//                                           `--._                         `-.                     /          /
//                                                `-.._                       `.                  |         .'
//                                                     `-.__                    `-.               /        /
//                                                          `-._                   `-.           /       .'
//                                                              ``-._       +---------`-.-------+----+  /
//                                                                   ``-._  |                        |.'
//                                                                        `-+   NetWork Simulator    +
//                                                                          |                        |
//                                                                          +------------------------+
//
//
//
// */
public class HolePunchingTestSimulator
        extends TestCase {

    public static final int OVERLAY_ID = 1;
    private static final Logger logger = LoggerFactory.getLogger(HolePunchingTestSimulator.class);
    String NatTypes = getClass().getSimpleName();
    private boolean testStatus = true;

    /**
     * Create the test case
     *
     * @param testName name of the test case
     */
    public HolePunchingTestSimulator(String testName) {
        super(testName);
    }

    /**
     * @return the suite of tests being tested
     */
    public static Test suite() {
        return new TestSuite(HolePunchingTestSimulator.class);
    }

//    public static void setTestObj(HolePunchingTestSimulator testObj) {
//        TestStunClientComponent.testObj = testObj;
//    }
//
//    public static class MsgTimeout extends Timeout {
//
//        public MsgTimeout(ScheduleTimeout request) {
//            super(request);
//        }
//    }
//
//    public static class StartTimeout extends Timeout {
//
//        public StartTimeout(ScheduleTimeout request) {
//            super(request);
//        }
//    }
//
//    public static class Client_A_Timeout extends Timeout {
//
//        public Client_A_Timeout(ScheduleTimeout request) {
//            super(request);
//        }
//    }
//
//    public static class Client_B_Timeout extends Timeout {
//
//        public Client_B_Timeout(ScheduleTimeout request) {
//            super(request);
//        }
//    }
//
//    public static class TestStunClientComponent extends ComponentDefinition {
//
//        private Component pmA;
//        private Component pmB;
//        private Component stunClientComp_A;
//        private Component stunClientComp_B;
//        private Component serverS1Comp;
//        private Component serverS2Comp;
//        private Component natComp_A;
//        private Component natComp_B;
//        private Component zServerComp;
//        private Component holePunchingClientComp_A;
//        private Component holePunchingClientComp_B;
//        private Component timer, networkSimulator;
//        private Component portReservoir_For_A;
//        private Component portReservoir_For_B;
//        private static HolePunchingTestSimulator testObj = null;
//        private Address stunClient_A_Address;
//        private Address stunClient_B_Address;
//        private Address serverS1Address;
//        private Address serverS2Address;
//        private VodAddress c1;
//        private VodAddress c2;
//        private VodAddress z1;
//        int client_A_ID = 10;
//        int client_B_ID = 11;
//        int nat_A_ID = 100;
//        int nat_B_ID = 101;
//        int networkSimulatorID = 1000;
//        InetAddress ip1, ip2, ip3, ip4;
//        int port = 3478;
//        int serverS1Port = port;
//        int serverS1ChangePort = port + 1;
//        int serverS2Port = port;
//        int serverS2ChangePort = port + 1;
//        int clientPort = 1234;
//        InetAddress natIP = null;
//        private ConcurrentHashMap<Integer, OpenedConnection> openedConnections_A
//                = new ConcurrentHashMap<Integer, OpenedConnection>();
//        private ConcurrentHashMap<Integer, OpenedConnection> openedConnections_B
//                = new ConcurrentHashMap<Integer, OpenedConnection>();
//        //Nat of client A
//        Nat.AllocationPolicy nat_A_AllocationPolicy;
//        Nat.AlternativePortAllocationPolicy nat_A_AlternativeAllocationPolicy;
//        Nat.MappingPolicy nat_A_MappingPolicy;
//        Nat.FilteringPolicy nat_A_FilteringPolicy;
//        //Nat of client B
//        Nat.AllocationPolicy nat_B_AllocationPolicy;
//        Nat.AlternativePortAllocationPolicy nat_B_AlternativeAllocationPolicy;
//        Nat.MappingPolicy nat_B_MappingPolicy;
//        Nat.FilteringPolicy nat_B_FilteringPolicy;
//        // Some combined values
//        int nat_A_RuleLifeTime;
//        int nat_B_RuleLifeTime;
//        int ClientATestDelay;
//        int ClientBTestDelay;
//        Nat nat_A = null; //response returned by the stun client
//        Nat nat_B = null; //response returned by the stun client
//        int client_A_TransactionID_Gen;
//        int client_B_TransactionID_Gen;
//        TimeoutId client_A_TimeoutId = UUID.nextUUID();
//        TimeoutId client_B_TimeoutId = UUID.nextUUID();
//        int expectedPongMessagesA = 0;
//        int expectedPongMessagesB = 0;
//        Nat.Type client_A_NatType = Nat.Type.NAT;
//        Nat.Type client_B_NatType = Nat.Type.NAT;
//        int retryDelay = 1 * 1000;
//        int ruleCleanupTimer = 500;
//
//        public static class TestMessage extends DirectMsg {
//
//            static final long serialVersionUID = 1L;
//            private TimeoutId id;
//
//            public TestMessage(VodAddress src, VodAddress dest, TimeoutId id) {
//                super(src, dest);
//                this.id = id;
//            }
//
//            public TimeoutId getId() {
//                return id;
//            }
//
//            @Override
//            public RewriteableMsg copy() {
//                return new TestMessage(vodSrc, vodDest, id);
//            }
//        }
//
//        public void destroyEveryThing() {
//
//            // send the stop messages
//            // unsubscribe
////            unsubscribe(handleStart, control);
//            unsubscribe(handleMsgTimeout, timer.getPositive(Timer.class));
//            unsubscribe(handleStartTimeout, timer.getPositive(Timer.class));
//            unsubscribe(handleStartPingPong_A, timer.getPositive(Timer.class));
//            unsubscribe(handleStartPingPong_B, timer.getPositive(Timer.class));
//            unsubscribe(handleGetNatTypeResponseFromClient_A, stunClientComp_A.getPositive(StunPort.class));
//            unsubscribe(handleNatTypeResponseRuleTimeoutFromClient_A, stunClientComp_A.getPositive(StunPort.class));
//            unsubscribe(handleGetNatTypeResponseFromClient_B, stunClientComp_B.getPositive(StunPort.class));
//            unsubscribe(handleNatTypeResponseRuleTimeoutFromClient_B, stunClientComp_B.getPositive(StunPort.class));
//            unsubscribe(handleOpenConnectionResponseFromHolePunchingClient_A, holePunchingClientComp_A.getPositive(HpClientPort.class));
//            unsubscribe(handleOpenConnectionResponseFromHolePunchingClient_B, holePunchingClientComp_B.getPositive(HpClientPort.class));
//            unsubscribe(handleRegisterWithRendezvousServerResponse_A, networkSimulator.getPositive(VodNetwork.class));
//            unsubscribe(handleRegisterWithRendezvousServerResponse_B, networkSimulator.getPositive(VodNetwork.class));
//            if (client_A_NatType == Nat.Type.OPEN) {
//                unsubscribe(handlePong_A, networkSimulator.getPositive(VodNetwork.class));
//                unsubscribe(handlePing_A, networkSimulator.getPositive(VodNetwork.class));
//            } else {
//                unsubscribe(handlePong_A, natComp_A.getPositive(VodNetwork.class));
//                unsubscribe(handlePing_A, natComp_A.getPositive(VodNetwork.class));
//            }
//
//            if (client_B_NatType == Nat.Type.OPEN) {
//                unsubscribe(handlePong_B, networkSimulator.getPositive(VodNetwork.class));
//                unsubscribe(handlePing_B, networkSimulator.getPositive(VodNetwork.class));
//            } else {
//                unsubscribe(handlePong_B, natComp_B.getPositive(VodNetwork.class));
//                unsubscribe(handlePing_B, natComp_B.getPositive(VodNetwork.class));
//            }
//
//            // disconnect components
//            // disconnecting client A
//            if (client_A_NatType != Nat.Type.OPEN) {
//                disconnect(stunClientComp_A.getNegative(UpnpPort.class), natComp_A.getPositive(UpnpPort.class));
//                disconnect(natComp_A.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class));
//                disconnect(stunClientComp_A.getNegative(VodNetwork.class), natComp_A.getPositive(VodNetwork.class));
//                disconnect(holePunchingClientComp_A.getNegative(VodNetwork.class), natComp_A.getPositive(VodNetwork.class));
////                disconnect(pmA.getNegative(GVodNetwork.class), natComp_A.getPositive(GVodNetwork.class));
//
//            } else {
//                // connect it to the simulator
//                disconnect(stunClientComp_A.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class));
//                disconnect(holePunchingClientComp_A.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class));
//            }
//
//            if (client_B_NatType != Nat.Type.OPEN) {
//                // connectiong client B
//                disconnect(stunClientComp_B.getNegative(UpnpPort.class), natComp_B.getPositive(UpnpPort.class));
//                disconnect(natComp_B.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class));
//                disconnect(stunClientComp_B.getNegative(VodNetwork.class), natComp_B.getPositive(VodNetwork.class));
//                disconnect(holePunchingClientComp_B.getNegative(VodNetwork.class), natComp_B.getPositive(VodNetwork.class));
////                disconnect(pmB.getNegative(GVodNetwork.class), natComp_B.getPositive(GVodNetwork.class));
//
//            } else {
//                disconnect(stunClientComp_B.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class));
//                disconnect(holePunchingClientComp_B.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class));
//            }
//
//            // disconnecting stun servers
//            disconnect(serverS1Comp.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class));
//            disconnect(serverS2Comp.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class));
//
//            // disconnecting zServer to the network simulator
//            disconnect(zServerComp.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class));
//
//            // disconnect timers
//            disconnect(serverS1Comp.getNegative(Timer.class), timer.getPositive(Timer.class));
//            disconnect(serverS2Comp.getNegative(Timer.class), timer.getPositive(Timer.class));
//            disconnect(stunClientComp_A.getNegative(Timer.class), timer.getPositive(Timer.class));
//            disconnect(stunClientComp_B.getNegative(Timer.class), timer.getPositive(Timer.class));
//            disconnect(holePunchingClientComp_A.getNegative(Timer.class), timer.getPositive(Timer.class));
//            disconnect(holePunchingClientComp_B.getNegative(Timer.class), timer.getPositive(Timer.class));
//            disconnect(zServerComp.getNegative(Timer.class), timer.getPositive(Timer.class));
//            disconnect(natComp_A.getNegative(Timer.class), timer.getPositive(Timer.class));
//            disconnect(natComp_B.getNegative(Timer.class), timer.getPositive(Timer.class));
//            disconnect(holePunchingClientComp_A.getNegative(NatNetworkControl.class),
//                    portReservoir_For_A.getPositive(NatNetworkControl.class));
//            disconnect(stunClientComp_A.getNegative(NatNetworkControl.class),
//                    portReservoir_For_A.getPositive(NatNetworkControl.class));
//
//            disconnect(holePunchingClientComp_B.getNegative(NatNetworkControl.class),
//                    portReservoir_For_B.getPositive(NatNetworkControl.class));
//            disconnect(stunClientComp_B.getNegative(NatNetworkControl.class),
//                    portReservoir_For_B.getPositive(NatNetworkControl.class));
//
//            // destroy components
//            destroy(stunClientComp_A);
//            destroy(stunClientComp_B);
//            destroy(serverS1Comp);
//            destroy(serverS2Comp);
//            destroy(zServerComp);
//            destroy(holePunchingClientComp_A);
//            destroy(holePunchingClientComp_B);
//            destroy(timer);
//            destroy(natComp_A);
//            destroy(natComp_B);
//            destroy(networkSimulator);
//        }
//
//        public void destroyAndPass() {
//            destroyEveryThing();
//            testObj.passTest();
//        }
//
//        public void destroyAndFail() {
//            destroyEveryThing();
//            testObj.failTest(true);
//        }
//
//        public TestStunClientComponent() {
//            stunClientComp_A = create(StunClient.class);
//            stunClientComp_B = create(StunClient.class);
//            serverS1Comp = create(StunServer.class);
//            serverS2Comp = create(StunServer.class);
//            zServerComp = create(RendezvousServer.class);
//            holePunchingClientComp_A = create(HpClient.class);
//            holePunchingClientComp_B = create(HpClient.class);
//            timer = create(JavaTimer.class);
//            natComp_A = create(DistributedNatGatewayEmulator.class);
//            natComp_B = create(DistributedNatGatewayEmulator.class);
//            networkSimulator = create(NetworkSimulator.class);
//            portReservoir_For_A = create(PortReservoirComp.class);
//            portReservoir_For_B = create(PortReservoirComp.class);
////            pmA = create(ParentMaker.class);
////            pmB = create(ParentMaker.class);
//
//            subscribe(handleStartTimeout, timer.getPositive(Timer.class));
//            ScheduleTimeout st = new ScheduleTimeout(1 * 1000);
//            StartTimeout startTimeout = new StartTimeout(st);
//            st.setTimeoutEvent(startTimeout);
//            trigger(st, timer.getPositive(Timer.class));
//
//        }
//        public Handler<StartTimeout> handleStartTimeout = new Handler<StartTimeout>() {
//            @Override
//            public void handle(StartTimeout event) {
//                initializeNatVariables(); // initialize the nat variables
//
////            subscribe(handleStart, control);
//                subscribe(handleMsgTimeout, timer.getPositive(Timer.class));
//                subscribe(handleStartPingPong_A, timer.getPositive(Timer.class));
//                subscribe(handleStartPingPong_B, timer.getPositive(Timer.class));
//                subscribe(handleGetNatTypeResponseFromClient_A, stunClientComp_A.getPositive(StunPort.class));
//                subscribe(handleNatTypeResponseRuleTimeoutFromClient_A, stunClientComp_A.getPositive(StunPort.class));
//                subscribe(handleGetNatTypeResponseFromClient_B, stunClientComp_B.getPositive(StunPort.class));
//                subscribe(handleNatTypeResponseRuleTimeoutFromClient_B, stunClientComp_B.getPositive(StunPort.class));
//                subscribe(handleOpenConnectionResponseFromHolePunchingClient_A, holePunchingClientComp_A.getPositive(HpClientPort.class));
//                subscribe(handleOpenConnectionResponseFromHolePunchingClient_B, holePunchingClientComp_B.getPositive(HpClientPort.class));
//                subscribe(handleRegisterWithRendezvousServerResponse_A, networkSimulator.getPositive(VodNetwork.class));
//                subscribe(handleRegisterWithRendezvousServerResponse_B, networkSimulator.getPositive(VodNetwork.class));
//
//                if (client_A_NatType == Nat.Type.OPEN) {
//                    subscribe(handlePong_A, networkSimulator.getPositive(VodNetwork.class));
//                    subscribe(handlePing_A, networkSimulator.getPositive(VodNetwork.class));
//                } else {
//                    subscribe(handlePong_A, natComp_A.getPositive(VodNetwork.class));
//                    subscribe(handlePing_A, natComp_A.getPositive(VodNetwork.class));
//                }
//
//                if (client_B_NatType == Nat.Type.OPEN) {
//                    subscribe(handlePong_B, networkSimulator.getPositive(VodNetwork.class));
//                    subscribe(handlePing_B, networkSimulator.getPositive(VodNetwork.class));
//                } else {
//                    subscribe(handlePong_B, natComp_B.getPositive(VodNetwork.class));
//                    subscribe(handlePing_B, natComp_B.getPositive(VodNetwork.class));
//                }
//
//                // kinda use less remove it later on
//                final class MessageDestinationFilter extends ChannelFilter<RewriteableMsg, Address> {
//
//                    public MessageDestinationFilter(Address address) {
//                        super(RewriteableMsg.class, address, true);
//                    }
//
//                    @Override
//                    public Address getValue(RewriteableMsg event) {
//                        return event.getDestination();
//                    }
//                }
//
////            try {
////                ip = event.getBoundIp();
////                natIP = event.getBoundIp();
////                ip = InetAddress.getLocalHost();
////                natIP = InetAddress.getLocalHost();
////            } catch (UnknownHostException ex) {
////                logger.error("UnknownHostException");
////                destroyAndFail();
////            }
//                try {
//                    ip1 = InetAddress.getByName("192.168.0.1");
//                    ip2 = InetAddress.getByName("192.168.0.2");
//                    ip3 = InetAddress.getByName("192.168.0.3");
//                    ip4 = InetAddress.getByName("192.168.0.4");
//                    natIP = InetAddress.getByName("192.168.0.5");
//                } catch (UnknownHostException ex) {
//                    HolePunchingTestSimulator.fail("Could not acquire ip addresses");
//                }
//
//                serverS1Address = new Address(ip3, serverS1Port, 1);
//                serverS2Address = new Address(ip4, serverS2Port, 2);
//                z1 = ToVodAddr.hpServer(serverS1Address);
//
//                stunClient_A_Address = new Address(ip1, clientPort, client_A_ID);
//                stunClient_B_Address = new Address(ip2, clientPort, client_B_ID);
//
//                // no need to filter the packets based on port. a peer may have many opened ports
//                final class MessageDestinationFilterBasedOnIPandID extends ChannelFilter<RewriteableMsg, IpIntPair> {
//
//                    String message = "";
//
//                    public MessageDestinationFilterBasedOnIPandID(IpIntPair kompicsIP, String msg) {
//                        super(RewriteableMsg.class, kompicsIP, true);
//                        message = msg;
//                    }
//
//                    @Override
//                    public IpIntPair getValue(RewriteableMsg event) {
//                        IpIntPair kompicsIP = new IpIntPair(event.getDestination().getIp(),
//                                event.getDestination().getId());
//                        HolePunchingTestSimulator.logger.trace(message + " FILTER is called. public point is " + kompicsIP + " event type is " + event.getClass().toString());
//                        return kompicsIP;
//                    }
//                }
//
//                // connecting client A 
//                if (client_A_NatType != Nat.Type.OPEN) {
//                    connect(stunClientComp_A.getNegative(UpnpPort.class), natComp_A.getPositive(UpnpPort.class));
//
//                    connect(natComp_A.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class),
//                            new MessageDestinationFilterBasedOnIPandID(new IpIntPair(natIP, nat_A_ID), "natA-sim"/*
//                             * only for debuging
//                             */));
//
//                    connect(stunClientComp_A.getNegative(VodNetwork.class), natComp_A.getPositive(VodNetwork.class),
//                            new MessageDestinationFilterBasedOnIPandID(new IpIntPair(stunClient_A_Address.getIp(), stunClient_A_Address.getId()), "clntA-natA"));
//                    // connecting hole punching clients
//                    // hole punching clients have same address as the stun clients coz they run on the same node
//                    connect(holePunchingClientComp_A.getNegative(VodNetwork.class), natComp_A.getPositive(VodNetwork.class),
//                            new MessageDestinationFilterBasedOnIPandID(new IpIntPair(stunClient_A_Address.getIp(), stunClient_A_Address.getId()), "HP_ClntA-natA"));
//
////                    connect(pmA.getNegative(GVodNetwork.class), natComp_A.getPositive(GVodNetwork.class),
////                            new MessageDestinationFilterBasedOnIPandID(new IpIntPair(stunClient_A_Address.getIp(), stunClient_A_Address.getId()), "pmA-natA"));
//                } else {
//                    // connect it to the simulator 
//                    connect(stunClientComp_A.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class),
//                            new MessageDestinationFilterBasedOnIPandID(new IpIntPair(stunClient_A_Address.getIp(), stunClient_A_Address.getId()), "clntA-Sim"));
//                    connect(holePunchingClientComp_A.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class),
//                            new MessageDestinationFilterBasedOnIPandID(new IpIntPair(stunClient_A_Address.getIp(), stunClient_A_Address.getId()), "HP_ClntA-Sim"));
//                }
//
//                if (client_B_NatType != Nat.Type.OPEN) {
//                    connect(stunClientComp_B.getNegative(UpnpPort.class), natComp_B.getPositive(UpnpPort.class));
//
//                    // connectiong client B
//                    connect(natComp_B.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class),
//                            new MessageDestinationFilterBasedOnIPandID(new IpIntPair(natIP, nat_B_ID), "natB-sim"/*
//                             * only for debuggin
//                             */));
//
//                    connect(stunClientComp_B.getNegative(VodNetwork.class), natComp_B.getPositive(VodNetwork.class),
//                            new MessageDestinationFilterBasedOnIPandID(new IpIntPair(stunClient_B_Address.getIp(), stunClient_B_Address.getId()), "clntB-natB"));
//
//                    connect(holePunchingClientComp_B.getNegative(VodNetwork.class), natComp_B.getPositive(VodNetwork.class),
//                            new MessageDestinationFilterBasedOnIPandID(new IpIntPair(stunClient_B_Address.getIp(), stunClient_B_Address.getId()), "HP_ClntB-natB"));
//
////                    connect(pmB.getNegative(GVodNetwork.class), natComp_B.getPositive(GVodNetwork.class),
////                            new MessageDestinationFilterBasedOnIPandID(new IpIntPair(stunClient_B_Address.getIp(), stunClient_B_Address.getId()), "pmB-natA"));
//                } else {
//                    connect(stunClientComp_B.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class),
//                            new MessageDestinationFilterBasedOnIPandID(new IpIntPair(stunClient_B_Address.getIp(), stunClient_B_Address.getId()), "clntB-Sim"));
//
//                    connect(holePunchingClientComp_B.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class),
//                            new MessageDestinationFilterBasedOnIPandID(new IpIntPair(stunClient_B_Address.getIp(), stunClient_B_Address.getId()), "HP_ClntB-Sim"));
//                }
//
//                // connecting stun servers
//                connect(serverS1Comp.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class),
//                        new MessageDestinationFilterBasedOnIPandID(new IpIntPair(serverS1Address.getIp(), serverS1Address.getId()), "sim-srv1"));
//
//                connect(serverS2Comp.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class),
//                        new MessageDestinationFilterBasedOnIPandID(new IpIntPair(serverS2Address.getIp(), serverS2Address.getId()), "sim-srv2"));
//
//                // connecting zServer to the network simulator
//                // server S1 and Z server run on the same node. there for they have same address
//                connect(zServerComp.getNegative(VodNetwork.class), networkSimulator.getPositive(VodNetwork.class),
//                        new MessageDestinationFilterBasedOnIPandID(new IpIntPair(serverS1Address.getIp(), serverS1Address.getId()), "sim_zServer"));
//
//                // connect timers
//                connect(serverS1Comp.getNegative(Timer.class), timer.getPositive(Timer.class));
//                connect(serverS2Comp.getNegative(Timer.class), timer.getPositive(Timer.class));
//                connect(stunClientComp_A.getNegative(Timer.class), timer.getPositive(Timer.class));
//                connect(stunClientComp_B.getNegative(Timer.class), timer.getPositive(Timer.class));
//                connect(holePunchingClientComp_A.getNegative(Timer.class), timer.getPositive(Timer.class));
//                connect(holePunchingClientComp_B.getNegative(Timer.class), timer.getPositive(Timer.class));
//                connect(zServerComp.getNegative(Timer.class), timer.getPositive(Timer.class));
//                connect(natComp_A.getNegative(Timer.class), timer.getPositive(Timer.class));
//                connect(natComp_B.getNegative(Timer.class), timer.getPositive(Timer.class));
//
//                connect(holePunchingClientComp_A.getNegative(NatNetworkControl.class),
//                        portReservoir_For_A.getPositive(NatNetworkControl.class));
//                connect(stunClientComp_A.getNegative(NatNetworkControl.class),
//                        portReservoir_For_A.getPositive(NatNetworkControl.class));
//
//                connect(holePunchingClientComp_B.getNegative(NatNetworkControl.class),
//                        portReservoir_For_B.getPositive(NatNetworkControl.class));
//                connect(stunClientComp_B.getNegative(NatNetworkControl.class),
//                        portReservoir_For_B.getPositive(NatNetworkControl.class));
//
//                // sending init messages to all the components
//                trigger(new NetworkSimulatorInit(), networkSimulator.getControl());
//
//                // initialize both stun servers i.e. s1 and s2
//                VodAddress g2 = ToVodAddr.stunServer(serverS2Address);
//                VodAddress g1 = ToVodAddr.stunServer(serverS1Address);
//                List<VodAddress> p1 = new ArrayList<VodAddress>();
//                p1.add(g2);
//                List<VodAddress> p2 = new ArrayList<VodAddress>();
//                p2.add(g1);
//                StunServerConfiguration ssc = StunServerConfiguration.build();
//
//                trigger(new StunServerInit(new SelfNoParents(g1), p1, ssc),
//                        serverS1Comp.getControl());
//                trigger(new StunServerInit(new SelfNoParents(g2), p2, ssc),
//                        // TODO S2 does not need the address of S1. change required
//                        serverS2Comp.getControl());
//
//                // initialize two stun client one for node a and other for node b
//                StunClientConfiguration sc = StunClientConfiguration.build().
//                        setRuleExpirationIncrement(3500).
//                        setUpnpEnable(false).
//                        setRto(retryDelay).
//                        setRuleExpirationMinWait(1000).
//                        setMinimumRtt(3 * 1000).
//                        setRandTolerance(10).
//                        setRtoRetries(0);
//
//                VodAddress ga = ToVodAddr.stunClient(stunClient_A_Address);
//                trigger(new StunClientInit(new SelfNoUtility(ga),
//                        0/*seed */,
//                        sc),
//                        stunClientComp_A.getControl());
//                VodAddress gb = ToVodAddr.stunClient(stunClient_B_Address);
//                trigger(new StunClientInit(new SelfNoUtility(gb),
//                        1/*seed */,
//                        sc),
//                        stunClientComp_B.getControl());
//
//                trigger(new PortInit(0), portReservoir_For_A.getControl());
//                trigger(new PortInit(0), portReservoir_For_B.getControl());
//
////                trigger(new ParentMakerInit(new SelfNoParents(ga), 1*1000, 1, 
////                        3000, 1.2d, 1, 2000), pmA.getControl());
////                trigger(new ParentMakerInit(new SelfNoParents(ga), 1*1000, 1, 
////                        3000, 1.2d, 1, 2000), pmB.getControl());
//                // initialize the z server
//                // Nat type for z-Server
//                trigger(new RendezvousServerInit(new SelfNoParents(g1),
//                        new ConcurrentHashMap<Integer, RegisteredClientRecord>(),
//                        RendezvousServerConfiguration.build()),
//                        zServerComp.getControl());
//
//                if (client_A_NatType != Nat.Type.OPEN) {
//                    trigger(new DistributedNatGatewayEmulatorInit(
//                            50000,
//                            nat_A_MappingPolicy,
//                            nat_A_AllocationPolicy,
//                            nat_A_AlternativeAllocationPolicy, /*
//                             * alternaive policy if there is clash using PP
//                             */
//                            nat_A_FilteringPolicy,
//                            client_A_NatType, /*
//                             * types are NAT OPEN and UPNP
//                             */
//                            ruleCleanupTimer /*
//                             * rule cleanup timer
//                             */,
//                            natIP /*
//                             * ip of NAT Gateway
//                             */,
//                            65533 /*
//                             * max port
//                             */,
//                            false /*
//                             * clashing overrides
//                             */,
//                            nat_A_RuleLifeTime /*
//                             * rule life time
//                             */,
//                            55 /*
//                             * rand port seed
//                             */, //TODO change it to random seed
//                            true/*
//                     * enable upnp
//                     */), natComp_A.getControl());
//                }
//
//                if (client_B_NatType != Nat.Type.OPEN) {
//                    trigger(new DistributedNatGatewayEmulatorInit(
//                            50000,
//                            nat_B_MappingPolicy,
//                            nat_B_AllocationPolicy,
//                            nat_B_AlternativeAllocationPolicy, /*
//                             * alternaive policy if there is clash using PP
//                             */
//                            nat_B_FilteringPolicy,
//                            client_B_NatType, /*
//                             * types are NAT OPEN and UPNP
//                             */
//                            ruleCleanupTimer/*
//                             * rule cleanup timer
//                             */,
//                            natIP /*
//                             * ip of NAT Gateway
//                             */,
//                            65533 /*
//                             * max port
//                             */,
//                            false /*
//                             * clashing overrides
//                             */,
//                            nat_B_RuleLifeTime /*
//                             * rule life time
//                             */,
//                            55 /*
//                             * rand port seed
//                             */, //TODO change it to random seed
//                            true /*
//                     * enable upnp
//                     */), natComp_B.getControl());
//                }
//
//                ScheduleTimeout stt = new ScheduleTimeout(600 * 1000);
//                MsgTimeout msgTimeout = new MsgTimeout(stt);
//                stt.setTimeoutEvent(msgTimeout);
//
//                Set<Address> servers = new HashSet<Address>();
//                servers.add(serverS1Address);
//                trigger(new GetNatTypeRequest(servers, false),
//                        stunClientComp_A.getPositive(StunPort.class));
//                trigger(stt, timer.getPositive(Timer.class));
//
//                ScheduleTimeout st1 = new ScheduleTimeout(600 * 1000);
//                MsgTimeout msgTimeout1 = new MsgTimeout(st1);
//                st1.setTimeoutEvent(msgTimeout1);
//
//                trigger(new GetNatTypeRequest(servers, false),
//                        stunClientComp_B.getPositive(StunPort.class));
//                trigger(st1, timer.getPositive(Timer.class));
//
//            }
//        };
//        public Handler<GetNatTypeResponseRuleExpirationTime> handleNatTypeResponseRuleTimeoutFromClient_A
//                = new Handler<GetNatTypeResponseRuleExpirationTime>() {
//                    @Override
//                    public void handle(GetNatTypeResponseRuleExpirationTime event) {
//                        HolePunchingTestSimulator.logger.debug("Rule life time value of Nat A is " + event.getRuleLifeTime());
//                        nat_A.setBindingTimeout(event.getRuleLifeTime());
//
//                // discovery process is complete
//                        // now ask the Hole punching client to establish connection between client A and B
//                        // through some zServer
//                        // register with zServer
//                        registerClientA();
//                    }
//                };
//
//        public void registerClientA() {
//
//            Self me = new SelfNoUtility(ToVodAddr.stunClient(stunClient_A_Address));
//            HpRegisterMsg.Request registerRequest = new HpRegisterMsg.Request(
//                    me.getAddress(), z1, 100);
//            trigger(registerRequest, natComp_A.getPositive(VodNetwork.class));
//        }
//        public Handler<HpRegisterMsg.Response> handleRegisterWithRendezvousServerResponse_A
//                = new Handler<HpRegisterMsg.Response>() {
//                    @Override
//                    public void handle(HpRegisterMsg.Response response) {
//                        if (response.getResponseType() == HpRegisterMsg.RegisterStatus.ACCEPT) {
//                            HolePunchingTestSimulator.logger.debug("Test Component: Client A successfully registered");
//
//                            Self me = new SelfNoUtility(ToVodAddr.stunClient(stunClient_A_Address));
//                            me.addParent(response.getSource());
//                            c2.addParent(response.getSource());
//
//                            // ask to open the connection
////                            OpenConnectionRequest request = new OpenConnectionRequest(
////                                    client_B_ID, 
////                                    nat_B,
////                                    serverS1Address/*zServer has the same address i.e. same node*/, nat_A);
//                            OpenConnectionRequest request = new OpenConnectionRequest(c2, false,
//                                    true, response.getTimeoutId());
////                                    z1);
//                            trigger(request, holePunchingClientComp_A.getPositive(HpClientPort.class));
//                        } else {
//                            HolePunchingTestSimulator.logger.debug("Test Component. Registration to zServer by Client A has failed");
//                        }
//                    }
//                };
//        public Handler<GetNatTypeResponseRuleExpirationTime> handleNatTypeResponseRuleTimeoutFromClient_B
//                = new Handler<GetNatTypeResponseRuleExpirationTime>() {
//                    @Override
//                    public void handle(GetNatTypeResponseRuleExpirationTime event) {
//                        HolePunchingTestSimulator.logger.debug("Rule life time value of Nat B is " + event.getRuleLifeTime());
//                        nat_B.setBindingTimeout(event.getRuleLifeTime());
//
//                // discovery process is complete
//                        // now ask the Hole punching client to establish connection between client A and B
//                        // through some zServer
//                        // register with zServer
//                        registerClientB();
//                    }
//                };
//
//        public void registerClientB() {
//            Self me = new SelfNoUtility(ToVodAddr.stunClient(stunClient_B_Address));
//            HpRegisterMsg.Request registerRequest = new HpRegisterMsg.Request(
//                    me.getAddress(), z1, 100);
//            trigger(registerRequest, natComp_B.getPositive(VodNetwork.class));
//        }
//        public Handler<HpRegisterMsg.Response> handleRegisterWithRendezvousServerResponse_B
//                = new Handler<HpRegisterMsg.Response>() {
//                    @Override
//                    public void handle(HpRegisterMsg.Response response) {
//                        if (response.getResponseType() == HpRegisterMsg.RegisterStatus.ACCEPT) {
//                            HolePunchingTestSimulator.logger.debug("Test Component: Client B successfully registered");
//
//                            Self me = new SelfNoUtility(ToVodAddr.stunClient(stunClient_A_Address));
//                            me.addParent(response.getSource());
//                            c1.addParent(response.getSource());
//
//                            // ask to open the connection
//                            OpenConnectionRequest request = new OpenConnectionRequest(c1, true,
//                                    true, response.getTimeoutId());
////                                    z1);
//                            trigger(request, holePunchingClientComp_B.getPositive(HpClientPort.class));
//                        } else {
//                            HolePunchingTestSimulator.logger.debug("Test Component. Registration to zServer by Client B has failed");
//                        }
//                    }
//                };
//        public Handler<OpenConnectionResponse> handleOpenConnectionResponseFromHolePunchingClient_A
//                = new Handler<OpenConnectionResponse>() {
//                    @Override
//                    public void handle(OpenConnectionResponse event) {
//                        if (event.getResponseType() == OpenConnectionResponseType.OK) {
//
//                            HolePunchingTestSimulator.logger.debug("Test Comp of Client A:  HP is successful");
//
//                            ScheduleTimeout st = new ScheduleTimeout(ClientATestDelay);
//                            Client_A_Timeout msgTimeout = new Client_A_Timeout(st);
//                            st.setTimeoutEvent(msgTimeout);
//                            trigger(st, timer.getPositive(Timer.class));
//
//                        } else {
//                            HolePunchingTestSimulator.logger.debug("Test Comp of Client A:  HP has FAILED");
//                        }
//                    }
//                };
//        public Handler<Client_A_Timeout> handleStartPingPong_A = new Handler<Client_A_Timeout>() {
//            @Override
//            public void handle(Client_A_Timeout event) {
//                HolePunchingTestSimulator.logger.debug("Test Comp of Client A:  Starting ping pong to test the connection");
//                expectedPongMessagesA++;
//                // get the opened connection
////                HPSessionKey key = new HPSessionKey(client_A_ID, client_B_ID);
//                OpenedConnection openedConnection = openedConnections_A.get(client_B_ID);
//                Address sourceAddress = new Address(ip1, openedConnection.getPortInUse(), client_A_ID);
//                TConnectionMsg.Ping ping = new TConnectionMsg.Ping(
//                        ToVodAddr.hpServer(sourceAddress),
//                        ToVodAddr.hpServer(openedConnection.getHoleOpened()),
//                        UUID.nextUUID());
//                trigger(ping, natComp_A.getPositive(VodNetwork.class));
//            }
//        };
//        public Handler<TConnectionMsg.Ping> handlePing_A
//                = new Handler<TConnectionMsg.Ping>() {
//                    @Override
//                    public void handle(TConnectionMsg.Ping event) {
//                        if (event.getDestination().getId() != client_A_ID) {
//                            return;
//                        }
//
//                        HolePunchingTestSimulator.logger.debug("Test Comp A: ping rcvd.");
//                        if (nat_A.getType() == Nat.Type.OPEN) {
//                            Address sourceAddress = new Address(ip1, 1234, client_A_ID);
//                            TConnectionMsg.Pong pong = new TConnectionMsg.Pong(
//                                    ToVodAddr.hpServer(sourceAddress),
//                                    event.getVodSource(), null);
//                            trigger(pong, networkSimulator.getPositive(VodNetwork.class));
//                        } else {
//                            // get the opened connection
////                            HPSessionKey key = new HPSessionKey(client_A_ID, event.getClientID());
//                            OpenedConnection openedConnection
//                            = openedConnections_A.get(event.getSource().getId());
//                            Address sourceAddress = new Address(ip1, openedConnection.getPortInUse(), client_A_ID);
//                            //HolePunchingTest.logger.debug("Test Comp A: hole on Bs nat is " + openedConnection.getHoleOpened());
//                            TConnectionMsg.Pong pong = new TConnectionMsg.Pong(
//                                    ToVodAddr.hpServer(sourceAddress),
//                                    ToVodAddr.hpServer(openedConnection.getHoleOpened()),
//                                    null);
//                            trigger(pong, natComp_A.getPositive(VodNetwork.class));
//                        }
//
//                    }
//                };
//        public Handler<TConnectionMsg.Pong> handlePong_A
//                = new Handler<TConnectionMsg.Pong>() {
//                    @Override
//                    public void handle(TConnectionMsg.Pong event) {
//                        if (event.getDestination().getId() != client_A_ID) {
//                            return;
//                        }
//                        expectedPongMessagesA--;
//                        HolePunchingTestSimulator.logger.debug("Test Comp A: pong rcvd. "
//                                + " Pongs left to receive: " + expectedPongMessagesA
//                                + " src: " + event.getSource() + " dest: " + event.getDestination());
//                        if (expectedPongMessagesA == 0) {
//                            destroyAndPass();
//                        }
//                    }
//                };
//        public Handler<TConnectionMsg.Ping> handlePing_B
//                = new Handler<TConnectionMsg.Ping>() {
//                    @Override
//                    public void handle(TConnectionMsg.Ping event) {
//                        if (event.getDestination().getId() != client_B_ID) {
//                            return;
//                        }
//                        HolePunchingTestSimulator.logger.debug("Test Comp B: ping rcvd Message: "
//                        );
//                        // sending pong back
//                        if (nat_B.getType() == Nat.Type.OPEN) {
//                            Address sourceAddress = new Address(ip2, 1234, client_B_ID);
//                            TConnectionMsg.Pong pong = new TConnectionMsg.Pong(
//                                    ToVodAddr.hpServer(sourceAddress),
//                                    event.getVodSource(), null);
//                            trigger(pong, networkSimulator.getPositive(VodNetwork.class));
//                        } else {
//                            // get the opened connection
////                            HPSessionKey key = new HPSessionKey(client_B_ID, event.getClientID());
//                            OpenedConnection openedConnection
//                            = openedConnections_B.get(event.getSource().getId());
//                            Address sourceAddress = null;
//                            VodAddress holeOpened = null;
//                            if (openedConnection != null) {
//                                sourceAddress = new Address(ip2, openedConnection.getPortInUse(), client_B_ID);
//                                HolePunchingTestSimulator.logger.debug("Test Comp B: hole on As nat is " + openedConnection.getHoleOpened());
//                                holeOpened
//                                = ToVodAddr.hpServer(openedConnection.getHoleOpened());
//                            } else {
//                                sourceAddress = new Address(ip2, event.getSource().getPort(), client_B_ID);
//                                Address openA = new Address(ip2, event.getSource().getPort(), client_B_ID);
//                                holeOpened = ToVodAddr.hpServer(openA);
//                            }
//                            TConnectionMsg.Pong pong = new TConnectionMsg.Pong(
//                                    ToVodAddr.hpServer(sourceAddress),
//                                    holeOpened, null);
//                            trigger(pong, natComp_B.getPositive(VodNetwork.class));
//                        }
//                    }
//                };
//        public Handler<TConnectionMsg.Pong> handlePong_B
//                = new Handler<TConnectionMsg.Pong>() {
//                    @Override
//                    public void handle(TConnectionMsg.Pong event) {
//                        if (event.getDestination().getId() != client_B_ID) {
//                            return;
//                        }
//                        HolePunchingTestSimulator.logger.debug("Test Comp B: pong rcvd Message: "
//                                + " src: " + event.getSource() + " dest: " + event.getDestination());
//                        expectedPongMessagesB--;
//                        if (expectedPongMessagesB == 0) {
//                            destroyAndPass();
//                        }
//                    }
//                };
//        public Handler<OpenConnectionResponse> handleOpenConnectionResponseFromHolePunchingClient_B
//                = new Handler<OpenConnectionResponse>() {
//                    @Override
//                    public void handle(OpenConnectionResponse event) {
//                        if (event.getResponseType() == OpenConnectionResponseType.OK) {
//                            HolePunchingTestSimulator.logger.debug("Test Comp of Client B:  HP is successful");
//                            ScheduleTimeout st = new ScheduleTimeout(ClientATestDelay);
//                            Client_B_Timeout msgTimeout = new Client_B_Timeout(st);
//                            st.setTimeoutEvent(msgTimeout);
//                            trigger(st, timer.getPositive(Timer.class));
//
//                        } else {
//                            HolePunchingTestSimulator.logger.debug("Test Comp of Client B:  HP has FAILED");
//                        }
//                    }
//                };
//        public Handler<Client_B_Timeout> handleStartPingPong_B = new Handler<Client_B_Timeout>() {
//            @Override
//            public void handle(Client_B_Timeout event) {
//                expectedPongMessagesB++;
//                HolePunchingTestSimulator.logger.debug("Test Comp of Client B:  "
//                        + "Starting ping pong to test the connection. Expected pongs: "
//                        + expectedPongMessagesB);
//
//                // get the opened connection
////                HPSessionKey key = new HPSessionKey(client_B_ID, client_A_ID);
//                OpenedConnection openedConnection = openedConnections_B.get(client_A_ID);
//                Address sourceAddress = new Address(ip2, openedConnection.getPortInUse(), client_B_ID);
//                TConnectionMsg.Ping ping = new TConnectionMsg.Ping(
//                        ToVodAddr.hpServer(sourceAddress),
//                        ToVodAddr.hpServer(openedConnection.getHoleOpened()),
//                        UUID.nextUUID());
//                HolePunchingTestSimulator.logger.debug("Test Comp B sending ping to dest " + ping.getDestination());
//                trigger(ping, natComp_B.getPositive(VodNetwork.class));
//            }
//        };
//        public Handler<GetNatTypeResponse> handleGetNatTypeResponseFromClient_A
//                = new Handler<GetNatTypeResponse>() {
//                    @Override
//                    public void handle(GetNatTypeResponse event) {
//
//                        if (event.getStatus() != GetNatTypeResponse.Status.SUCCEED) {
//                            logger.error("STUN could not determine client A's nat type: "
//                                    + event.getStatus());
//                            destroyAndFail();
//                            return;
//                        }
//
//                        HolePunchingTestSimulator.logger.debug("Nat type of client A is:" + event.getNat().toString());
//                        nat_A = event.getNat();
//                        c1 = new VodAddress(stunClient_A_Address, OVERLAY_ID, nat_A);
//
//                        // initialze two hole punching clients. one for node a and other for node b
//                        Self self = new SelfNoUtility(c1);
//                        trigger(new HpClientInit(self,
//                                        openedConnections_A,
//                                        HpClientConfiguration.build().
//                                        setScanRetries(0).
//                                        setScanningEnabled(true).
//                                        setSessionExpirationTime(30 * 1000).
//                                        setRto(retryDelay),
//                                        new ConcurrentSkipListSet<Integer>()
//                                ),
//                                holePunchingClientComp_A.getControl());
//
//                        boolean pass = true;
//                        if (nat_A.isOpen()) {
//                            registerClientA(); // no need to wait for rule timeout response etc
//                        } else if (nat_A_MappingPolicy == nat_A.getMappingPolicy()
//                        && nat_A_AllocationPolicy == nat_A.getAllocationPolicy()
//                        && nat_A_FilteringPolicy == nat_A.getFilteringPolicy()) {
//                            if (nat_A_AllocationPolicy == Nat.AllocationPolicy.PORT_PRESERVATION) {
//                                pass = true;
////                                if (nat_A_AlternativeAllocationPolicy != nat_A.getAlternativePortAllocationPolicy()) {
////                                    pass = false;
////                                }
//                            }
//                        } else {
//                            pass = false;
//                        }
//
//                        if (pass) {
//                            //destroyAndPass();
//                        } else {
//                            destroyAndFail();
//                        }
//                    }
//                };
//        public Handler<GetNatTypeResponse> handleGetNatTypeResponseFromClient_B
//                = new Handler<GetNatTypeResponse>() {
//                    @Override
//                    public void handle(GetNatTypeResponse event) {
//                        if (event.getStatus() != GetNatTypeResponse.Status.SUCCEED) {
//                            logger.error("STUN could not determine client B's nat type: "
//                                    + event.getStatus());
//                            destroyAndFail();
//                            return;
//                        }
//
//                        HolePunchingTestSimulator.logger.debug("Nat type of client B is: " + event.getNat().toString());
//                        nat_B = event.getNat();
//                        c2 = new VodAddress(stunClient_B_Address, OVERLAY_ID, nat_B);
//
//                        Self self = new SelfNoUtility(c2);
//                        trigger(new HpClientInit(self,
//                                        openedConnections_B,
//                                        HpClientConfiguration.build().
//                                        setScanRetries(5).
//                                        setScanningEnabled(true).
//                                        setSessionExpirationTime(30 * 1000).
//                                        setRto(retryDelay),
//                                        new ConcurrentSkipListSet<Integer>()), holePunchingClientComp_B.getControl());
//
//                        boolean pass = true;
//                        if (nat_B.getType() == Nat.Type.UPNP
//                        || nat_B.getType() == Nat.Type.OPEN) {
//                            registerClientB();
//                        } else if (nat_B_MappingPolicy == nat_B.getMappingPolicy()
//                        && nat_B_AllocationPolicy == nat_B.getAllocationPolicy()
//                        && nat_B_FilteringPolicy == nat_B.getFilteringPolicy()) {
//                            if (nat_B_AllocationPolicy == Nat.AllocationPolicy.PORT_PRESERVATION) {
//                                pass = true;
////                                if (nat_B_AlternativeAllocationPolicy != nat_B.getAlternativePortAllocationPolicy()) {
////                                    pass = false;
////                                }
//                            }
//                        } else {
//                            pass = false;
//                        }
//                        if (pass) {
//                            //destroyAndPass();
//                        } else {
//                            destroyAndFail();
//                        }
//                    }
//                };
//        public Handler<MsgTimeout> handleMsgTimeout = new Handler<MsgTimeout>() {
//            @Override
//            public void handle(MsgTimeout event) {
//                destroyAndFail();
//            }
//        };
//
//        final void initializeNatVariables() {
//            HashMap<String, Nat.MappingPolicy> mappingHash = new HashMap<String, Nat.MappingPolicy>();
//            HashMap<String, Nat.AllocationPolicy> allocationHash = new HashMap<String, Nat.AllocationPolicy>();
//            HashMap<String, Nat.AlternativePortAllocationPolicy> altAllocationHash = new HashMap<String, Nat.AlternativePortAllocationPolicy>();
//            HashMap<String, Nat.FilteringPolicy> filteringHash = new HashMap<String, Nat.FilteringPolicy>();
//
//            mappingHash.put("m(EI)", Nat.MappingPolicy.ENDPOINT_INDEPENDENT);
//            mappingHash.put("m(HD)", Nat.MappingPolicy.HOST_DEPENDENT);
//            mappingHash.put("m(PD)", Nat.MappingPolicy.PORT_DEPENDENT);
//
//            allocationHash.put("a(PP)", Nat.AllocationPolicy.PORT_PRESERVATION);
//            allocationHash.put("a(PC)", Nat.AllocationPolicy.PORT_CONTIGUITY);
//            allocationHash.put("a(RD)", Nat.AllocationPolicy.RANDOM);
//
//            altAllocationHash.put("alt(PC)", Nat.AlternativePortAllocationPolicy.PORT_CONTIGUITY);
//            altAllocationHash.put("alt(RD)", Nat.AlternativePortAllocationPolicy.RANDOM);
//
//            filteringHash.put("f(EI)", Nat.FilteringPolicy.ENDPOINT_INDEPENDENT);
//            filteringHash.put("f(HD)", Nat.FilteringPolicy.HOST_DEPENDENT);
//            filteringHash.put("f(PD)", Nat.FilteringPolicy.PORT_DEPENDENT);
//
//            testObj.NatTypes = currentTestName;
//
//            StringTokenizer stz = new StringTokenizer(testObj.NatTypes, "_{}X");
//
//            String token = stz.nextToken();
//            if (token.equals("OPEN")) {
//                client_A_NatType = Nat.Type.OPEN;
//            } else if (token.equals("UPNP")) {
//                client_A_NatType = Nat.Type.UPNP;
//            } else {
//                nat_A_MappingPolicy = (Nat.MappingPolicy) setVariable(mappingHash, token);
//                nat_A_AllocationPolicy = (Nat.AllocationPolicy) setVariable(allocationHash, (String) stz.nextElement());
//                nat_A_AlternativeAllocationPolicy = (Nat.AlternativePortAllocationPolicy) setVariable(altAllocationHash, (String) stz.nextElement());
//                nat_A_FilteringPolicy = (Nat.FilteringPolicy) setVariable(filteringHash, (String) stz.nextElement());
//            }
//
//            token = stz.nextToken();
//            if (token.equals("OPEN")) {
//                client_B_NatType = Nat.Type.OPEN;
//            } else if (token.equals("UPNP")) {
//                client_B_NatType = Nat.Type.UPNP;
//            } else {
//                nat_B_MappingPolicy = (Nat.MappingPolicy) setVariable(mappingHash, token);
//                nat_B_AllocationPolicy = (Nat.AllocationPolicy) setVariable(allocationHash, (String) stz.nextElement());
//                nat_B_AlternativeAllocationPolicy = (Nat.AlternativePortAllocationPolicy) setVariable(altAllocationHash, (String) stz.nextElement());
//                nat_B_FilteringPolicy = (Nat.FilteringPolicy) setVariable(filteringHash, (String) stz.nextElement());
//            }
//
//            Properties prop = new Properties();
//            try {
//                prop.load(new FileInputStream("src" + File.separator + "test" + File.separator
//                        + "resources" + File.separator + "log4j.properties"));
//
//            } catch (IOException ex) {
//                java.util.logging.Logger.getLogger(HolePunchingTestSimulator.class.getName()).log(Level.SEVERE, null, ex);
//            }
//
//            String strNatARuleLifeTime = prop.getProperty("NatARuleLifeTime");
//            String strNatBRuleLifeTime = prop.getProperty("NatBRuleLifeTime");
//            String strClientATestDelay = prop.getProperty("ClientATestDelay");
//            String strClientBTestDelay = prop.getProperty("ClientBTestDelay");
//
//            nat_A_RuleLifeTime = 5 * 1000;
////                    Integer.parseInt(strNatARuleLifeTime);
//            nat_B_RuleLifeTime = 5 * 1000;
////                    Integer.parseInt(strNatBRuleLifeTime);
//            ClientATestDelay = Integer.parseInt(strClientATestDelay);
//            ClientBTestDelay = Integer.parseInt(strClientBTestDelay);
//
//            HolePunchingTestSimulator.logger.debug("Client1 T(" + client_A_NatType + "), m(" + nat_A_MappingPolicy + ") a(" + nat_A_AllocationPolicy + ") alt_a(" + nat_A_AlternativeAllocationPolicy + ") f(" + nat_A_FilteringPolicy + ") RuleLifeTime: " + nat_A_RuleLifeTime);
//            HolePunchingTestSimulator.logger.debug("Client2 T(" + client_B_NatType + "), m(" + nat_B_MappingPolicy + ") a(" + nat_B_AllocationPolicy + ") alt_a(" + nat_B_AlternativeAllocationPolicy + ") f(" + nat_B_FilteringPolicy + ") RuleLifeTime: " + nat_B_RuleLifeTime);
//            HolePunchingTestSimulator.logger.debug("Client A test delay " + ClientATestDelay + " Client B Test delay " + ClientBTestDelay);
//        }
//
//        Object setVariable(HashMap map, String hashKey) {
//            Object obj = map.get(hashKey);
//            if (obj == null) {
//                HolePunchingTestSimulator.logger.error("Incorrect File Name Format. hash key " + hashKey);
//                System.exit(0);
//            }
//
//            return obj;
//        }
//
//        int getTransactionIDForClient_A() {
//            return client_A_TransactionID_Gen++;
//        }
//
//        int getTransactionIDForClient_B() {
//            return client_B_TransactionID_Gen++;
//        }
//    }
//    private static final int EVENT_COUNT = 1;
//    private static Semaphore semaphore = new Semaphore(0);
//    private static String currentTestName;
//    private static String[] tests = {
//        /**
//         * ************************Very Simple Hole Punching **************
//         */
//        //        "{UPNP}_{m(EI)_a(PP)_alt(PC)_f(EI)}",
//        //        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{UPNP}",
//        //        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{UPNP}",
//        //        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{UPNP}",
//        //        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{UPNP}",
//        //        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{UPNP}",
//        //        "{m(EI)_a(PP)_alt(PC)_f(PD)}_{UPNP}",
//        //        "{m(HD)_a(PC)_alt(PC)_f(PD)}_{UPNP}",
//        //        "{m(PD)_a(PP)_alt(PC)_f(PD)}_{UPNP}",
//        //
//
//        //        "{OPEN}_{m(PD)_a(RD)_alt(PC)_f(PD)}",
//        //        "{m(EI)_a(PP)_alt(PC)_f(PD)}_{OPEN}",
//        //        "{OPEN}_{m(PD)_a(PC)_alt(PC)_f(EI)}",
//        //        "{m(EI)_a(PC)_alt(PC)_f(PD)}_{OPEN}",
//        //        "{OPEN}_{m(EI)_a(PP)_alt(PC)_f(PD)}",
//        //        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{OPEN}",
//        //        "{OPEN}_{m(HD)_a(PC)_alt(PC)_f(PD)}",
//        //
//
//        //        "{m(EI)_a(PC)_alt(PC)_f(PD)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRC-PRC
//
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PP)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PP)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PP)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PP)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PP)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PP)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PP)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PP)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PP)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(PD)}", // SHP
//        //        //
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PP)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PP)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PP)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PP)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PP)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // SHP
//
//        //
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PP)_alt(PC)_f(EI)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PP)_alt(PC)_f(HD)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PP)_alt(PC)_f(HD)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PP)_alt(PC)_f(HD)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        //
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(PD)}", // SHP
//        //
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        //
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        //
//        "{m(EI)_a(RD)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(RD)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(RD)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(EI)_a(RD)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(RD)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(RD)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(EI)_a(RD)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(RD)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(PD)}", // SHP
//        "{m(EI)_a(RD)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(PD)}", // SHP
//        //
//        "{m(HD)_a(RD)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(RD)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(HD)_a(RD)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(RD)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(HD)_a(RD)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // SHP
//
//        //
//        "{m(PD)_a(RD)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(EI)}", // SHP
//        "{m(PD)_a(RD)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(PD)_a(RD)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        "{m(PD)_a(RD)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // SHP
//        ////        /********************** PRP ********************************/
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(PP)_alt(PC)_f(HD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(PP)_alt(PC)_f(HD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(PP)_alt(PC)_f(HD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(PP)_alt(PC)_f(HD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(PP)_alt(PC)_f(PD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(PP)_alt(PC)_f(PD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(PP)_alt(PC)_f(PD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(PC)_alt(PC)_f(HD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(PC)_alt(PC)_f(HD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(RD)_alt(PC)_f(PD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(RD)_alt(PC)_f(PD)}", // PRP
//        "{m(EI)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(RD)_alt(PC)_f(PD)}", // PRP
//        //
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(PP)_alt(PC)_f(HD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(PP)_alt(PC)_f(HD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(PP)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(PP)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(PP)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(PC)_alt(PC)_f(HD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(PC)_alt(PC)_f(HD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(RD)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(RD)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(RD)_alt(PC)_f(PD)}", // PRP
//
//        //
//        "{m(PD)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(PP)_alt(PC)_f(HD)}", // PRP
//        "{m(PD)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(PC)_alt(PC)_f(HD)}", // PRP
//        "{m(PD)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(PC)_alt(PC)_f(HD)}", // PRP
//        "{m(PD)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // PRP
//        "{m(PD)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // PRP
//        "{m(PD)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // PRP
//        "{m(PD)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // PRP
//        //        /************************* PRC***********************************/
//        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{m(EI)_a(PC)_alt(PC)_f(HD)}", // PRC
//        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{m(HD)_a(PC)_alt(PC)_f(HD)}", // PRC
//        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // PRC
//        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRC
//        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRC
//        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRC
//        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // PRC
//        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // PRC
//        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // PRC
//        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{m(EI)_a(RD)_alt(PC)_f(PD)}", // PRC
//        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{m(HD)_a(RD)_alt(PC)_f(PD)}", // PRC
//        "{m(EI)_a(PC)_alt(PC)_f(HD)}_{m(PD)_a(RD)_alt(PC)_f(PD)}", // PRC
//        //
//        "{m(HD)_a(PC)_alt(PC)_f(HD)}_{m(HD)_a(PC)_alt(PC)_f(HD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(HD)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(HD)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(HD)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(HD)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(HD)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(HD)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(HD)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(HD)}_{m(EI)_a(RD)_alt(PC)_f(PD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(HD)}_{m(HD)_a(RD)_alt(PC)_f(PD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(HD)}_{m(PD)_a(RD)_alt(PC)_f(PD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(PD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(PD)}", // PRC
//        "{m(HD)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(PD)}", // PRC
//        //
//        "{m(PD)_a(PC)_alt(PC)_f(HD)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // PRC
//        "{m(PD)_a(PC)_alt(PC)_f(HD)}_{m(EI)_a(RD)_alt(PC)_f(HD)}", // PRC
//        "{m(PD)_a(PC)_alt(PC)_f(HD)}_{m(HD)_a(RD)_alt(PC)_f(HD)}", // PRC
//        "{m(PD)_a(PC)_alt(PC)_f(HD)}_{m(PD)_a(RD)_alt(PC)_f(HD)}", // PRC
//        //
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PP)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PP)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PP)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(RD)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(RD)_alt(PC)_f(PD)}", // PRP
//        "{m(HD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(RD)_alt(PC)_f(PD)}", // PRP
//        //
//        ////
//        ////        /************* PRP-PRP ******************************************/
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PP)_alt(PC)_f(PD)}", // PRP-PRP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PP)_alt(PC)_f(PD)}", // PRP-PRP
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PP)_alt(PC)_f(PD)}", // PRP-PRP
//        //
//        "{m(PD)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(PP)_alt(PC)_f(PD)}", // PRP-PRP
//        "{m(PD)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(PP)_alt(PC)_f(PD)}", // PRP-PRP
//        "{m(PD)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(PP)_alt(PC)_f(PD)}", // PRP-PRP
//        //
//        "{m(EI)_a(PP)_alt(PC)_f(PD)}_{m(EI)_a(PP)_alt(PC)_f(PD)}", // PRP-PRP
//        "{m(EI)_a(PP)_alt(PC)_f(PD)}_{m(HD)_a(PP)_alt(PC)_f(PD)}", // PRP-PRP
//
//        // FAILED A UNIT TEST ONCE
//        //        "{m(EI)_a(PP)_alt(PC)_f(PD)}_{m(PD)_a(PP)_alt(PC)_f(PD)}", // PRP-PRP
//
//        "{m(HD)_a(PP)_alt(PC)_f(PD)}_{m(HD)_a(PP)_alt(PC)_f(PD)}", // PRP-PRP
//        // FAILED A UNIT TEST ONCE
//        //        "{m(HD)_a(PP)_alt(PC)_f(PD)}_{m(PD)_a(PP)_alt(PC)_f(PD)}", // PRP-PRP
//        //
//        // FAILED A UNIT TEST ONCE
//        //        "{m(PD)_a(PP)_alt(PC)_f(PD)}_{m(PD)_a(PP)_alt(PC)_f(PD)}", // PRP-PRP
//        ////
//        ////        /********************** PRC-PRC**************************************/
//        "{m(PD)_a(PC)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRC-PRC
//        "{m(PD)_a(PC)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRC-PRC
//        "{m(PD)_a(PC)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRC-PRC
//        //
//        "{m(PD)_a(PC)_alt(PC)_f(HD)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRC-PRC
//        "{m(PD)_a(PC)_alt(PC)_f(HD)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRC-PRC
//        "{m(PD)_a(PC)_alt(PC)_f(HD)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRC-PRC
//        //
//        "{m(EI)_a(PC)_alt(PC)_f(PD)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRC-PRC
//        "{m(EI)_a(PC)_alt(PC)_f(PD)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRC-PRC
//        //        
//        //        // FAILED IN UNIT TESTING
//        //        "{m(EI)_a(PC)_alt(PC)_f(PD)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRC-PRC
//        //        //
//        "{m(HD)_a(PC)_alt(PC)_f(PD)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRC-PRC
//
//        // FAILED UNIT TEST
//        //        "{m(HD)_a(PC)_alt(PC)_f(PD)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRC-PRC
//        // FAILED UNIT TEST
//        //        "{m(PD)_a(PC)_alt(PC)_f(PD)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRC-PRC
//        //        /********************* PRP-PRC *****************************************/
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//        "{m(PD)_a(PP)_alt(PC)_f(EI)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//        "{m(PD)_a(PP)_alt(PC)_f(HD)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//        "{m(PD)_a(PP)_alt(PC)_f(HD)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//        "{m(PD)_a(PP)_alt(PC)_f(HD)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//        "{m(EI)_a(PP)_alt(PC)_f(PD)}_{m(PD)_a(PC)_alt(PC)_f(EI)}", // PRP-PRC
//        "{m(EI)_a(PP)_alt(PC)_f(PD)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // PRP-PRC
//        "{m(EI)_a(PP)_alt(PC)_f(PD)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//        "{m(EI)_a(PP)_alt(PC)_f(PD)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//        // FAILED UNIT TEST
//        //        "{m(EI)_a(PP)_alt(PC)_f(PD)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//        "{m(HD)_a(PP)_alt(PC)_f(PD)}_{m(PD)_a(PC)_alt(PC)_f(EI)}", // PRP-PRC
//        "{m(HD)_a(PP)_alt(PC)_f(PD)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // PRP-PRC
//        "{m(HD)_a(PP)_alt(PC)_f(PD)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//        "{m(HD)_a(PP)_alt(PC)_f(PD)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//        // FAILED UNIT TEST
//        //        "{m(HD)_a(PP)_alt(PC)_f(PD)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//        //
//        "{m(PD)_a(PP)_alt(PC)_f(PD)}_{m(PD)_a(PC)_alt(PC)_f(EI)}", // PRP-PRC
//        "{m(PD)_a(PP)_alt(PC)_f(PD)}_{m(PD)_a(PC)_alt(PC)_f(HD)}", // PRP-PRC
//    // FAILED UNIT TEST
//    //        "{m(PD)_a(PP)_alt(PC)_f(PD)}_{m(EI)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//    // FAILED UNIT TEST
//    //        "{m(PD)_a(PP)_alt(PC)_f(PD)}_{m(HD)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//    // FAILED UNIT TEST
//    //        "{m(PD)_a(PP)_alt(PC)_f(PD)}_{m(PD)_a(PC)_alt(PC)_f(PD)}", // PRP-PRC
//    };
//
//    @Override
//    public void runTest() {
////        // for running few tests
////        String someTests[]=
////        { "{m(EI)_a(PC)_alt(PC)_f(HD)}_{OPEN}",
////        "{OPEN}_{m(HD)_a(PC)_alt(PC)_f(PD)}",
////        };
////        tests = someTests;
//
////        // for running all tests defined in the above array
//        for (int i = 0; i < tests.length; i++) {
//            currentTestName = tests[i];
//            testApp();
//        }
//
//    }
//
//    public void testApp() {
//        setTestObj(this);
//        setName(currentTestName);
//
//        logger.debug("---------------------------------------------------------------------------------------------------");
//        logger.debug(currentTestName);
//        logger.debug("---------------------------------------------------------------------------------------------------");
//
////        Kompics.createAndStart(TestStunClientComponent.class, 1);
////        try {
////            HolePunchingTestSimulator.semaphore.acquire(EVENT_COUNT);
////            logger.debug("Exiting unit test....");
////        } catch (InterruptedException e) {
////            HolePunchingTestSimulator.semaphore.release();
////            assert (false);
////        } finally {
////            Kompics.shutdown();
////        }
//        if (testStatus) {
//            assertTrue(true);
//        } else {
//            assertTrue(false);
//        }
//    }
//
//    public void passTest() {
//        assertTrue(true);
//        HolePunchingTestSimulator.semaphore.release();
//    }
//
//    public void failTest(boolean release) {
//        testStatus = false;
//        HolePunchingTestSimulator.semaphore.release();
//    }
}
